home *** CD-ROM | disk | FTP | other *** search
- /*
- * RZBrowserCell
- *
- * A subclass of BrowserCell supporting fixed and variable position tabs,
- * multi-font text and inline graphics.
- *
- * Here is an example of setting up a Browser to use a RZBrowserCell:
- *
- * // create a prototype cell for the browser
- * id cellPrototype = [[RZBrowserCell alloc] init];
- *
- * // initialize the tab stops
- * // fixed tab at 10 pixels
- * [cellPrototype addFixedTab:10.0];
- *
- * // proportional tab at 20% with min at 30 and max at 600 pixels
- * [cellPrototype addProportionalTab:0.2 min:30 max:600];
- *
- * // fixed tab 60 pixels from right side
- * [cellPrototype addFixedTab:-60.0];
- *
- * // make sure to set the prototype before we've loaded any columns
- * [browser setCellPrototype:cellPrototype];
- * [browser loadColumnZero];
- * [[browser window] makeKeyAndOrderFront:self];
- *
- *
- * You may freely copy, distribute and reuse the code in this example.
- * This code is provided AS IS without warranty of any kind, expressed
- * or implied, as to its fitness for any particular use.
- *
- * Copyright 1995 Ralph Zazula (rzazula@next.com). All Rights Reserved.
- *
- */
-
-
- #import "RZBrowserCell.h"
- #import "RZSortedList.h"
- #import "RZTextToken.h"
- #import "RZTabStop.h"
- #import "RZSimpleString.h"
- #import "RZRefCountedList.h"
- #import <appkit/appkit.h>
-
- #define BORDER 1
-
- @interface RZBrowserCell(Private)
- - _addTab:(RZTabStop *)aTab;
- - _addText:(RZTextToken *)aText;
- - _drawToken:(RZTextToken *)token inside:(const NXRect *)cellFrame inView:controlView;
- @end
-
- @implementation RZBrowserCell
-
- - copyFromZone:(NXZone *)zone
- {
- if(self = [super copyFromZone:zone]) {
- if(tabStops) {
- [tabStops addReference];
- }
- if(textTokens) {
- [textTokens addReference];
- }
- }
- return self;
- }
-
- - free
- {
- if(tabStops) {
- tabStops = [[tabStops freeObjects] free];
- }
- if(textTokens) {
- textTokens = [[textTokens freeObjects] free];
- }
- return [super free];
- }
-
- - setFont:fontObj
- {
- [super setFont:fontObj];
- /*
- * save this info so we don't have to look it up every time we draw
- * Note: support for a TextCell is a font object
- */
- NXTextFontInfo(support, &ascender, &descender, &lineHeight);
- return self;
- }
-
- - calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
- {
- NXRect b;
-
- [super calcCellSize:theSize inRect:aRect];
- [[self controlView] getBounds:&b];
- theSize->width = b.size.width;
- return self;
- }
-
- - drawInside:(const NXRect *)cellFrame inView:controlView
- {
- int i, count;
-
- if([[self font] screenFont]) {
- [[[self font] screenFont] set];
- } else {
- [[self font] set];
- }
-
- /* erase the cell */
- PSsetgray((cFlags1.state || cFlags1.highlighted) ? NX_WHITE : NX_LTGRAY);
- NXRectFill(cellFrame);
-
- /* draw the individual tokens */
- count = [textTokens count];
- for(i=0; i<count; i++) {
- [self _drawToken:(RZTextToken *)[textTokens objectAt:i]
- inside:cellFrame inView:controlView];
- }
-
- #if BORDER
- /* all drawing from now on will be in dark gray */
- PSsetgray(NX_DKGRAY);
-
- /* draw the two dark gray lines above and below the cell */
- if (cFlags1.state || cFlags1.highlighted) {
- NXRect rectArray[2];
- /*
- * draw 1-pixel tall rectangles instead of lines (this is faster than
- * PSmoveto(); PSlineto()).
- */
- NXSetRect(&(rectArray[0]), NX_X(cellFrame), NX_Y(cellFrame),
- NX_WIDTH(cellFrame), 1.0);
- NXSetRect(&(rectArray[1]), NX_X(cellFrame), NX_MAXY(cellFrame) - 1.0,
- NX_WIDTH(cellFrame), 1.0);
-
- /* using NXRectFillList is faster than separate calls to NXRectFill */
- NXRectFillList(rectArray, 2);
- }
- #endif
-
- return self;
- }
-
- - highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag
- {
- if (cFlags1.highlighted != flag) {
- cFlags1.highlighted = flag;
- [self drawInside:cellFrame inView:controlView];
- }
- return self;
- }
-
- /*** manipulating tabs ***/
-
- - addProportionalTab:(float)position
- {
- return [self addProportionalTab:position min:0.0 max:0.0];
- }
-
- - addProportionalTab:(float)position min:(float)minPos max:(float)maxPos
- {
- id aTab = [[RZTabStop alloc] initProportional:position min:minPos max:maxPos];
- [self _addTab:aTab];
- return self;
- }
-
- - addFixedTab:(float)position
- {
- id aTab = [[RZTabStop alloc] initFixed:position];
- [self _addTab:aTab];
- return self;
- }
-
- - clearTabs
- {
- if(tabStops) {
- [tabStops freeObjects];
- }
- return self;
- }
-
- /*** manipulating text tokens ***/
-
- - setText:(const char *)format at:(unsigned)index font:(char)font color:(char)color, ...
- {
- va_list args;
- static char buf[1024];
-
- va_start(args, format);
- vsprintf(buf, format, args);
-
- [self _addText:[[RZTextToken alloc] initText:buf at:index font:font color:color]];
-
- return self;
- }
-
- - setText:(const char *)format at:(unsigned)index, ...
- {
- va_list args;
- static char buf[1024];
-
- va_start(args, format);
- vsprintf(buf, format, args);
-
- [self _addText:[[RZTextToken alloc] initText:buf at:index]];
-
- return self;
- }
-
- - setText:(const char *)format at:(unsigned)index font:(char)font, ...
- {
- va_list args;
- static char buf[1024];
-
- va_start(args, format);
- vsprintf(buf, format, args);
-
- [self _addText:[[RZTextToken alloc] initText:buf at:index font:font color:0]];
-
- return self;
- }
-
- - setText:(const char *)format at:(unsigned)index color:(char)color, ...
- {
- va_list args;
- static char buf[1024];
-
- va_start(args, format);
- vsprintf(buf, format, args);
-
- [self _addText:[[RZTextToken alloc] initText:buf at:index font:0 color:color]];
-
- return self;
- }
-
- - clearText
- {
- if(textTokens) {
- [textTokens freeObjects];
- }
- return self;
- }
-
- /*** manipulating icons ***/
-
- - setImageNamed:(const char *)name at:(unsigned)index
- {
- [self _addText:[[RZTextToken alloc] initImage:name at:index]];
- return self;
- }
-
- /*** archiving ***/
-
- - write:(NXTypedStream *)ts
- {
- [super write:ts];
- NXWriteTypes(ts, "fff@@", &ascender, &descender, &lineHeight, &tabStops, &textTokens);
- return self;
- }
-
- - read:(NXTypedStream *)ts
- {
- [super read:ts];
- NXReadTypes(ts, "fff@@", &ascender, &descender, &lineHeight, &tabStops, &textTokens);
- return self;
- }
-
- @end
-
- @implementation RZBrowserCell(Private)
-
- - _addTab:(RZTabStop *)aTab
- {
- if(!tabStops) {
- tabStops = [[RZRefCountedList alloc] init];
- }
- [tabStops addObject:aTab];
- return self;
- }
-
- - _addText:(RZTextToken *)aText
- {
- int i;
-
- if(!textTokens) {
- textTokens = [[RZSortedList alloc] init];
- }
- /* remove any tokens at the same index */
- for(i=0; i<[textTokens count]; i++) {
- if([(RZTextToken *)[textTokens objectAt:i] position] == [aText position]) {
- [[textTokens removeObjectAt:i] free];
- }
- }
- [textTokens addObject:aText];
- return self;
- }
-
- - _drawToken:(RZTextToken *)token inside:(const NXRect *)cellFrame inView:controlView
- {
- static id textCell = nil;
-
- switch([token isText]) {
- case YES : { // text
- NXRect rect = *cellFrame;
- RZTabStop *thisStop, *nextStop;
- float thisStopPos, nextStopPos;
-
- if(!textCell) {
- textCell = [[TextFieldCell alloc] init];
- [textCell setWrap:NO];
- }
- [textCell setFont:[self font]];
-
- thisStop = [tabStops objectAt:[token position]];
- nextStop = [tabStops objectAt:([token position] + 1)];
-
- if([thisStop fixed]) {
- thisStopPos = [thisStop position];
- if(thisStopPos < 0.0) {
- thisStopPos += NX_WIDTH(cellFrame);
- }
- } else {
- thisStopPos = [thisStop position] * NX_WIDTH(cellFrame);
-
- if(([thisStop max] > 0.0) && (thisStopPos > [thisStop max])) {
- thisStopPos = [thisStop max];
- }
- if(thisStopPos < [thisStop min]) {
- thisStopPos = [thisStop min];
- }
- }
-
- if(nextStop) {
- if([nextStop fixed] ) {
- nextStopPos = [nextStop position];
- if(nextStopPos < 0.0) {
- nextStopPos += NX_WIDTH(cellFrame);
- }
- } else {
- nextStopPos = [nextStop position] * NX_WIDTH(cellFrame);
-
- if(([nextStop max] > 0.0) && (nextStopPos > [nextStop max])) {
- nextStopPos = [nextStop max];
- }
- if(nextStopPos < [nextStop min]) {
- nextStopPos = [nextStop min];
- }
- }
- } else {
- nextStopPos = 0.0;
- }
-
- /* move to the correct tab position */
- if(nextStopPos > 0.0) {
- NX_WIDTH(&rect) = nextStopPos - thisStopPos;
- } else {
- NX_WIDTH(&rect) -= thisStopPos;
- }
-
- NX_X(&rect) = thisStopPos;
- // NX_Y(&rect) += descender - 1;
-
- /* set the gray level */
- switch([token color]) {
- default :
- case 0 :
- [textCell setTextGray:NX_BLACK];
- break;
- case 1 :
- [textCell setTextGray:NX_DKGRAY];
- break;
- case 2 :
- case 3 :
- if(cFlags1.state || cFlags1.highlighted) {
- [textCell setTextGray:NX_LTGRAY];
- } else {
- [textCell setTextGray:NX_WHITE];
- }
- break;
- }
-
- /* set the font */
- {
- id newFont;
- char buf[128];
- switch([token font]) {
- default :
- case 0 :
- sprintf(buf, "%s", [[self font] familyName]);
- newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont];
- break;
- case 1 :
- sprintf(buf, "%s-Bold", [[self font] familyName]);
- newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont];
- break;
- case 2 :
- sprintf(buf, "%s-Oblique", [[self font] familyName]);
- newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont];
- break;
- case 3 :
- sprintf(buf, "%s-BoldOblique", [[self font] familyName]);
- newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont];
- break;
- }
- [textCell setFont:newFont];
- }
-
- [textCell setStringValue:(char *)[[token data] string]];
- [textCell drawInside:&rect inView:controlView];
- break;
- }
-
- case NO : { // icon
- float thisStopPos;
- RZTabStop *thisStop = [tabStops objectAt:[token position]];
- NXPoint p = cellFrame->origin;
- NXSize imageSize;
-
- if([thisStop fixed]) {
- thisStopPos = [thisStop position];
- if(thisStopPos < 0.0) {
- thisStopPos += NX_WIDTH(cellFrame);
- }
- } else {
- thisStopPos = [thisStop position] * NX_WIDTH(cellFrame);
-
- if(([thisStop max] > 0.0) && (thisStopPos > [thisStop max])) {
- thisStopPos = [thisStop max];
- }
- if(thisStopPos < [thisStop min]) {
- thisStopPos = [thisStop min];
- }
- }
-
- [[token data] getSize:&imageSize];
- p.x += thisStopPos;
- p.y += NX_HEIGHT(cellFrame) - (NX_HEIGHT(cellFrame) - imageSize.height) / 2.0;
- [[token data] composite:NX_SOVER toPoint:&p];
-
- break;
- }
-
- }
- return self;
- }
-
- @end
-